#include <iostream>

using std::cout;
using std::endl;

class Base
{
public:
    Base(long base = 0)
    : _base(base)
    {
        cout << "Base(long  = 0)" << endl;
    }

    ~Base()
    {
        cout << "~Base()" <<  endl;
    }

    virtual
    void func()
    {
        cout << "virtual void Base::func()" << endl;
    }

    virtual
    void gunc()
    {
        cout << "virtual void Base::gunc()" << endl;
    }

    virtual
    void hunc()
    {
        cout << "virtual void Base::hunc()" << endl;
    }
private:
    long _base;
};

class Derived
: public Base
{
public:
    Derived(long base = 0, long derived = 0)
    : Base(base)
    , _derived(derived)
    {
        cout << "Derived(long  = 0, long = 0)" << endl;
    }

    ~Derived()
    {
        cout << "~Derived()" <<  endl;
    }

    virtual
    void func() override
    {
        cout << "virtual void Derived::func()" << endl;
    }

    virtual
    void gunc() override
    {
        cout << "virtual void Derived::gunc()" << endl;
    }

    virtual
    void hunc() override
    {
        cout << "virtual void Derived::hunc()" << endl;
    }
private:
    long _derived;
};

void tmp()
{

}
void test()
{
    cout << "sizeof(Derived) = " << sizeof(Derived) << endl;
    cout << endl;

    //验证虚表存在的时候，就使用了C语言中的指针的概念，使用指针
    //进行强转，解引用，偏移
    //虚表是存在的,虚表存在只读段，对于普通单继承而言，虚表
    //只有一个

    Derived derived(10, 20);
    printf("打印对象derived = %p\n", &derived);
    printf("虚函数指针的地址 = %p\n", (long *)&derived);
    printf("虚表的地址 = %p\n", (long *)*(long *)&derived);
    printf("虚函数入口地址 = %p\n", 
           (long *)*(long *)*(long *)&derived);
    printf("&\"helo\" = %p\n", &"hello");
    printf("test = %p\n", test);

    cout << endl << "-----" << endl;
    //typdef int A;
    /* typedef void (*)() pFunc */
    typedef void (*pFunc)();//C中的写法
    /* using pFunc = void (*)();//C++中的写法 */
    /* pFunc pf = tmp; */ 
    pFunc pf = (pFunc)*( (long *)*(long *)&derived );
    pf();//调用虚函数
    printf("第一个虚函数入口地址 = %p\n", pf); 
    
    cout << endl;
    pf = (pFunc)*( (long *)*(long *)&derived  + 1);
    pf();//调用虚函数
    printf("第二个虚函数入口地址 = %p\n", pf); 

    cout << endl;
    pf = (pFunc)*( (long *)*(long *)&derived  + 2);
    pf();//调用虚函数
    printf("第三个虚函数入口地址 = %p\n", pf); 

    cout << endl << endl;
    Derived derived2(100, 200);
    printf("打印对象derived2 = %p\n", &derived2);
    printf("虚函数指针的地址 = %p\n", (long *)&derived2);
    printf("虚表的地址 = %p\n", (long *)*(long *)&derived2);

    cout << endl << endl;
    cout << "_base = " <<  *((long *)&derived + 1) << endl;
    cout << "_derived = " <<  *((long *)&derived + 2) << endl;
}

int main(int argc, char *argv[])
{
    test();
    return 0;
}


